```html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Spring Security 安全框架深度解析</title>
    <link href="https://cdn.staticfile.org/tailwindcss/2.2.19/tailwind.min.css" rel="stylesheet">
    <link href="https://cdn.staticfile.org/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
    <link href="https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@400;500;600;700&family=Noto+Sans+SC:wght@300;400;500;700&display=swap" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/mermaid@latest/dist/mermaid.min.js"></script>
    <style>
        :root {
            --primary: #4F46E5;
            --primary-light: #818CF8;
            --primary-dark: #3730A3;
            --secondary: #10B981;
            --dark: #1F2937;
            --light: #F3F4F6;
            --accent: #E11D48;
        }
        body {
            font-family: 'Noto Sans SC', 'Helvetica Neue', Arial, sans-serif;
            color: var(--dark);
            line-height: 1.6;
            background-color: #fafafa;
        }
        h1, h2, h3, h4 {
            font-family: 'Noto Serif SC', serif;
            font-weight: 600;
            color: var(--dark);
        }
        .hero {
            background: linear-gradient(135deg, var(--primary) 0%, var(--primary-dark) 100%);
            color: white;
        }
        .card {
            transition: all 0.3s ease;
            border-radius: 12px;
            box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
            overflow: hidden;
        }
        .card:hover {
            transform: translateY(-5px);
            box-shadow: 0 10px 20px rgba(0, 0, 0, 0.1);
        }
        .btn-primary {
            background-color: var(--primary);
            transition: all 0.3s ease;
        }
        .btn-primary:hover {
            background-color: var(--primary-dark);
            transform: translateY(-2px);
        }
        .feature-icon {
            background-color: rgba(79, 70, 229, 0.1);
            color: var(--primary);
        }
        .code-block {
            font-family: 'Courier New', monospace;
            background-color: #f8f8f8;
            border-left: 4px solid var(--primary);
            border-radius: 4px;
        }
        .dropped-capital::first-letter {
            float: left;
            font-size: 3.5em;
            line-height: 0.8;
            margin-right: 0.1em;
            color: var(--primary);
            font-weight: bold;
        }
        .timeline-item {
            position: relative;
            padding-left: 40px;
            margin-bottom: 30px;
        }
        .timeline-item::before {
            content: '';
            position: absolute;
            left: 0;
            top: 0;
            width: 20px;
            height: 20px;
            border-radius: 50%;
            background-color: var(--primary);
            border: 4px solid white;
            box-shadow: 0 0 0 2px var(--primary);
        }
        .timeline-item::after {
            content: '';
            position: absolute;
            left: 9px;
            top: 25px;
            width: 2px;
            height: calc(100% - 20px);
            background-color: #e5e7eb;
        }
        .timeline-item:last-child::after {
            display: none;
        }
    </style>
</head>
<body class="antialiased">
    <!-- Hero Section -->
    <section class="hero py-20 px-4 md:px-0">
        <div class="container mx-auto max-w-6xl text-center">
            <div class="flex justify-center mb-6">
                <div class="w-24 h-24 bg-white rounded-full flex items-center justify-center shadow-lg">
                    <i class="fas fa-shield-alt text-4xl" style="color: var(--primary);"></i>
                </div>
            </div>
            <h1 class="text-4xl md:text-5xl font-bold mb-6">Spring Security 安全框架</h1>
            <p class="text-xl md:text-2xl opacity-90 max-w-3xl mx-auto mb-8">基于Spring的强大安全框架，为您的应用程序提供全方位的安全防护</p>
            <div class="flex flex-wrap justify-center gap-4">
                <a href="#introduction" class="btn-primary text-white px-8 py-3 rounded-full font-medium">开始探索</a>
                <a href="#environment" class="bg-white text-primary px-8 py-3 rounded-full font-medium">快速开始</a>
            </div>
        </div>
    </section>

    <!-- Introduction Section -->
    <section id="introduction" class="py-16 px-4 md:px-0">
        <div class="container mx-auto max-w-6xl">
            <div class="text-center mb-16">
                <span class="inline-block px-4 py-1 bg-primary-light text-primary rounded-full text-sm font-medium mb-3">概述</span>
                <h2 class="text-3xl font-bold mb-4">Spring Security 介绍</h2>
                <div class="w-20 h-1 bg-primary mx-auto"></div>
            </div>

            <div class="grid md:grid-cols-2 gap-8 mb-16">
                <div>
                    <div class="card bg-white p-8 h-full">
                        <div class="flex items-center mb-4">
                            <div class="feature-icon w-12 h-12 rounded-full flex items-center justify-center mr-4">
                                <i class="fas fa-layer-group text-xl"></i>
                            </div>
                            <h3 class="text-xl font-bold">框架定位</h3>
                        </div>
                        <p class="dropped-capital">Spring Security是基于Spring应用程序提供声明式安全保护的安全性框架，它提供了完整的安全性解决方案，能够在web请求级别和方法调用级别处理身份验证和授权，它充分使用了依赖注入和面向切面的技术。</p>
                        <p class="mt-4">Spring Security的前身是Acegi Security，后来成为了Spring在安全领域的顶级项目，并正式更名到Spring名下，成为Spring全家桶中的一员，所以Spring Security很容易地集成到基于Spring的应用中。</p>
                    </div>
                </div>
                <div>
                    <div class="card bg-white p-8 h-full">
                        <div class="flex items-center mb-4">
                            <div class="feature-icon w-12 h-12 rounded-full flex items-center justify-center mr-4">
                                <i class="fas fa-fingerprint text-xl"></i>
                            </div>
                            <h3 class="text-xl font-bold">认证与授权</h3>
                        </div>
                        <p>Spring Security在用户认证方面支持众多主流认证标准，包括但不限于HTTP基本认证、HTTP表单验证、HTTP摘要认证、OpenID和LDAP等。在用户授权方面，Spring Security不仅支持最常用的基于URL的Web请求授权，还支持基于角色的访问控制(RBAC)以及访问控制列表(ACL)等。</p>
                        <div class="mt-6">
                            <div class="mermaid">
                                graph TD
                                    A[客户端请求] --> B{认证?}
                                    B -->|是| C[授权检查]
                                    B -->|否| D[重定向到登录]
                                    C --> E{有权限?}
                                    E -->|是| F[访问资源]
                                    E -->|否| G[拒绝访问]
                            </div>
                        </div>
                    </div>
                </div>
            </div>

            <div class="card bg-white p-8 mb-16">
                <div class="flex items-center mb-6">
                    <div class="feature-icon w-12 h-12 rounded-full flex items-center justify-center mr-4">
                        <i class="fas fa-shield-virus text-xl"></i>
                    </div>
                    <h3 class="text-xl font-bold">主要安全功能</h3>
                </div>
                <div class="grid md:grid-cols-3 gap-6">
                    <div class="border-l-4 border-primary pl-4">
                        <h4 class="font-bold text-lg mb-2">认证</h4>
                        <p>确定主体的过程，当未认证的主体访问系统资源时，系统会对主体的身份进行验证，确定该主体是否有合法的身份。</p>
                    </div>
                    <div class="border-l-4 border-secondary pl-4">
                        <h4 class="font-bold text-lg mb-2">授权</h4>
                        <p>在主体认证结束后，判断该认证主体是否有权限去访问某些资源，没有权限的访问将被系统拒绝。</p>
                    </div>
                    <div class="border-l-4 border-accent pl-4">
                        <h4 class="font-bold text-lg mb-2">攻击防护</h4>
                        <p>提供对CSRF、会话固定等常见攻击的防护机制，保障系统安全。</p>
                    </div>
                </div>
            </div>
        </div>
    </section>

    <!-- Core Concepts Section -->
    <section class="py-16 bg-gray-50 px-4 md:px-0">
        <div class="container mx-auto max-w-6xl">
            <div class="text-center mb-16">
                <span class="inline-block px-4 py-1 bg-primary-light text-primary rounded-full text-sm font-medium mb-3">核心概念</span>
                <h2 class="text-3xl font-bold mb-4">权限相关概念</h2>
                <div class="w-20 h-1 bg-primary mx-auto"></div>
            </div>

            <div class="grid md:grid-cols-3 gap-8 mb-12">
                <div class="card bg-white p-8 text-center">
                    <div class="w-16 h-16 bg-primary-light text-primary rounded-full flex items-center justify-center mx-auto mb-4">
                        <i class="fas fa-user text-2xl"></i>
                    </div>
                    <h3 class="text-xl font-bold mb-3">主体(Principal)</h3>
                    <p>使用系统的用户或设备或从其他系统远程登录的用户等。</p>
                </div>
                <div class="card bg-white p-8 text-center">
                    <div class="w-16 h-16 bg-primary-light text-primary rounded-full flex items-center justify-center mx-auto mb-4">
                        <i class="fas fa-key text-2xl"></i>
                    </div>
                    <h3 class="text-xl font-bold mb-3">认证(Authentication)</h3>
                    <p>权限管理系统确认一个主体的身份，允许主体进入系统。</p>
                </div>
                <div class="card bg-white p-8 text-center">
                    <div class="w-16 h-16 bg-primary-light text-primary rounded-full flex items-center justify-center mx-auto mb-4">
                        <i class="fas fa-user-shield text-2xl"></i>
                    </div>
                    <h3 class="text-xl font-bold mb-3">授权(Authorization)</h3>
                    <p>将操作系统的"权力""授予""主体"，这样主体就具备了操作系统中特定功能的能力。</p>
                </div>
            </div>

            <div class="card bg-white p-8">
                <h3 class="text-xl font-bold mb-4">认证与授权流程</h3>
                <div class="mermaid">
                    sequenceDiagram
                        participant C as 客户端
                        participant S as 服务器
                        C->>S: 请求资源(未认证)
                        S->>C: 返回401/重定向到登录页
                        C->>S: 提交凭证(用户名/密码)
                        S->>S: 验证凭证
                        alt 认证成功
                            S->>C: 返回认证令牌
                            C->>S: 携带令牌请求资源
                            S->>S: 检查权限
                            alt 有权限
                                S->>C: 返回请求的资源
                            else 无权限
                                S->>C: 返回403禁止访问
                            end
                        else 认证失败
                            S->>C: 返回错误信息
                        end
                </div>
            </div>
        </div>
    </section>

    <!-- Environment Setup Section -->
    <section id="environment" class="py-16 px-4 md:px-0">
        <div class="container mx-auto max-w-6xl">
            <div class="text-center mb-16">
                <span class="inline-block px-4 py-1 bg-primary-light text-primary rounded-full text-sm font-medium mb-3">实践</span>
                <h2 class="text-3xl font-bold mb-4">环境搭建</h2>
                <div class="w-20 h-1 bg-primary mx-auto"></div>
            </div>

            <div class="grid md:grid-cols-2 gap-8 mb-12">
                <div>
                    <div class="card bg-white p-8">
                        <h3 class="text-xl font-bold mb-4">POM依赖</h3>
                        <pre class="code-block p-4 overflow-x-auto"><code class="language-xml">&lt;dependency&gt;
    &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
    &lt;artifactId&gt;spring-boot-starter-security&lt;/artifactId&gt;
&lt;/dependency&gt;

&lt;dependency&gt;
    &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
    &lt;artifactId&gt;spring-boot-starter-web&lt;/artifactId&gt;
&lt;/dependency&gt;</code></pre>
                        <div class="mt-4 flex items-center text-sm text-gray-600">
                            <i class="fas fa-info-circle mr-2"></i>
                            <span>引入这两个依赖后，Spring Security会自动启用基本安全配置</span>
                        </div>
                    </div>
                </div>
                <div>
                    <div class="card bg-white p-8">
                        <h3 class="text-xl font-bold mb-4">控制器示例</h3>
                        <pre class="code-block p-4 overflow-x-auto"><code class="language-java">@Controller
public class UserController {

    @RequestMapping(value = "/hello")
    @ResponseBody
    public String hello(){
        System.out.println("UserController.hello");
        return "Hello Spring Security";
    }
}</code></pre>
                        <div class="mt-4 flex items-center text-sm text-gray-600">
                            <i class="fas fa-exclamation-triangle mr-2"></i>
                            <span>默认情况下，所有端点都需要认证</span>
                        </div>
                    </div>
                </div>
            </div>

            <div class="card bg-white p-8 mb-12">
                <h3 class="text-xl font-bold mb-4">默认安全行为</h3>
                <p class="mb-4">Spring Boot项目引入了Spring Security以后，自动装配了Spring Security的环境，Spring Security的默认配置是要求经过了HTTP Basic认证成功后才可以访问到URL对应的资源，且默认的用户名是user，密码是自动随机生成一串UUID字符串，输出到了控制台日志里。</p>
                <div class="grid md:grid-cols-2 gap-6">
                    <div>
                        <div class="border rounded-lg overflow-hidden">
                            <img src="https://cdn.nlark.com/yuque/0/2022/png/21449790/1651304591794-1c657439-d0af-4c14-b965-695e68636267.png" alt="Spring Security登录弹窗" class="w-full h-auto">
                        </div>
                        <p class="text-center text-sm text-gray-600 mt-2">默认的HTTP Basic认证弹窗</p>
                    </div>
                    <div>
                        <div class="border rounded-lg overflow-hidden">
                            <img src="https://cdn.nlark.com/yuque/0/2022/png/21449790/1651304601097-09eab964-d8c2-4c68-a9f2-672576663807.png" alt="控制台输出的随机密码" class="w-full h-auto">
                        </div>
                        <p class="text-center text-sm text-gray-600 mt-2">控制台输出的随机密码</p>
                    </div>
                </div>
            </div>
        </div>
    </section>

    <!-- Authentication Section -->
    <section class="py-16 bg-gray-50 px-4 md:px-0">
        <div class="container mx-auto max-w-6xl">
            <div class="text-center mb-16">
                <span class="inline-block px-4 py-1 bg-primary-light text-primary rounded-full text-sm font-medium mb-3">身份认证</span>
                <h2 class="text-3xl font-bold mb-4">身份认证方式</h2>
                <div class="w-20 h-1 bg-primary mx-auto"></div>
            </div>

            <div class="mb-12">
                <div class="card bg-white p-8 mb-8">
                    <h3 class="text-xl font-bold mb-4">配置文件方式</h3>
                    <pre class="code-block p-4 overflow-x-auto"><code class="language-yaml">spring:
  security:
    user:
      name: admin
      password: 123</code></pre>
                    <div class="mt-4 flex items-center text-sm text-gray-600">
                        <i class="fas fa-lightbulb mr-2"></i>
                        <span>简单场景下使用，不适合生产环境</span>
                    </div>
                </div>

                <div class="card bg-white p-8">
                    <h3 class="text-xl font-bold mb-4">自定义实现类(推荐)</h3>
                    <p class="mb-4">通过UserDetailsService来查询用户的密码，最后把用户封装成一个User返回给SpringSecurity。</p>
                    
                    <div class="mb-6">
                        <h4 class="font-bold mb-2">MyUserDetailsService</h4>
                        <pre class="code-block p-4 overflow-x-auto"><code class="language-java">@Configuration
public class MyUserDetailsService implements UserDetailsService {

    @Autowired
    private BCryptPasswordEncoder passwordEncoder;

    @Override
    public UserDetails loadUserByUsername(String username) {
        // 实际项目中应从数据库查询
        String password = passwordEncoder.encode("123");
        List&lt;GrantedAuthority&gt; authorities = 
            AuthorityUtils.createAuthorityList("admin");
        
        return new User(username, password, authorities);
    }
}</code></pre>
                    </div>

                    <div>
                        <h4 class="font-bold mb-2">SpringSecurityConfig</h4>
                        <pre class="code-block p-4 overflow-x-auto"><code class="language-java">@Configuration
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsService userDetailsService;

    @Bean
    public BCryptPasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService)
            .passwordEncoder(passwordEncoder());
    }
}</code></pre>
                    </div>
                </div>
            </div>
        </div>
    </section>

    <!-- Advanced Topics Section -->
    <section class="py-16 px-4 md:px-0">
        <div class="container mx-auto max-w-6xl">
            <div class="text-center mb-16">
                <span class="inline-block px-4 py-1 bg-primary-light text-primary rounded-full text-sm font-medium mb-3">高级主题</span>
                <h2 class="text-3xl font-bold mb-4">高级功能与配置</h2>
                <div class="w-20 h-1 bg-primary mx-auto"></div>
            </div>

            <div class="grid md:grid-cols-2 gap-8 mb-12">
                <div>
                    <div class="card bg-white p-8 h-full">
                        <h3 class="text-xl font-bold mb-4">自定义JSON登录</h3>
                        <pre class="code-block p-4 overflow-x-auto"><code class="language-java">@Component
public class LoginFilter extends UsernamePasswordAuthenticationFilter {
    
    public LoginFilter() {
        this.setPostOnly(false);
        this.setRequiresAuthenticationRequestMatcher(
            new AntPathRequestMatcher("/userLogin","GET"));
    }
    
    @Override
    public void setAuthenticationManager(AuthenticationManager manager) {
        super.setAuthenticationManager(manager);
    }
    
    @Override
    protected void successfulAuthentication(...) {
        // 登录成功处理
        ResponceUtils.out(response, R.ok().put("msg","登录成功"));
    }
    
    @Override
    protected void unsuccessfulAuthentication(...) {
        // 登录失败处理
        ResponceUtils.out(response, R.error("用户名或密码错误"));
    }
}</code></pre>
                    </div>
                </div>
                <div>
                    <div class="card bg-white p-8 h-full">
                        <h3 class="text-xl font-bold mb-4">用户注销配置</h3>
                        <pre class="code-block p-4 overflow-x-auto"><code class="language-java">http.formLogin()
    .loginPage("/toLogin")
    .loginProcessingUrl("/login") 
    .defaultSuccessUrl("/toSuccess")
    
.and()
    .logout() // 注销配置
    .logoutUrl("/toLogout")
    .logoutSuccessUrl("/logout-success")
    .addLogoutHandler((request, response, auth) -> {
        // 自定义注销处理
    })
    .logoutSuccessHandler((request, response, auth) -> {
        // 注销成功处理
    })
.and().csrf().disable();</code></pre>
                    </div>
                </div>
            </div>

            <div class="card bg-white p-8 mb-12">
                <h3 class="text-xl font-bold mb-4">权限控制方式</h3>
                <div class="grid md:grid-cols-3 gap-6 mb-6">
                    <div>
                        <h4 class="font-bold mb-2">表达式控制</h4>
                        <pre class="code-block p-4 overflow-x-auto"><code class="language-java">http.authorizeRequests()
    .antMatchers("/admin/**").hasRole("ADMIN")
    .antMatchers("/user/**").hasAnyRole("ADMIN", "USER")
    .anyRequest().authenticated();</code></pre>
                    </div>
                    <div>
                        <h4 class="font-bold mb-2">注解控制</h4>
                        <pre class="code-block p-4 overflow-x-auto"><code class="language-java">@PreAuthorize("hasRole('ADMIN')")
@GetMapping("/admin")
public String adminPage() {
    return "admin";
}</code></pre>
                    </div>
                    <div>
                        <h4 class="font-bold mb-2">动态权限</h4>
                        <pre class="code-block p-4 overflow-x-auto"><code class="language-java">.anyRequest().access(
    "@urlAuthService.hasPermission(request,authentication)"
)</code></pre>
                    </div>
                </div>
            </div>
        </div>
    </section>

    <!-- CSRF Section -->
    <section class="py-16 bg-gray-50 px-4 md:px-0">
        <div class="container mx-auto max-w-6xl">
            <div class="text-center mb-16">
                <span class="inline-block px-4 py-1 bg-primary-light text-primary rounded-full text-sm font-medium mb-3">安全防护</span>
                <h2 class="text-3xl font-bold mb-4">CSRF 防护</h2>
                <div class="w-20 h-1 bg-primary mx-auto"></div>
            </div>

            <div class="grid md:grid-cols-2 gap-8 mb-12">
                <div>
                    <div class="card bg-white p-8 h-full">
                        <h3 class="text-xl font-bold mb-4">CSRF 是什么？</h3>
                        <p class="mb-4">CSRF（Cross-site request forgery），中文名称：跨站请求伪造，也被称为：one click attack/session riding。</p>
                        <p class="mb-6">攻击者盗用了你的身份，以你的名义发送恶意请求。CSRF能够做的事情包括：以你名义发送邮件，发消息，盗取你的账号，甚至于购买商品，虚拟货币转账......</p>
                        <div class="border rounded-lg overflow-hidden">
                            <img src="https://cdn.nlark.com/yuque/0/2022/png/21449790/1651304657808-c7d512fc-3c44-4b35-8115-8a184ca119fc.png" alt="CSRF攻击示意图" class="w-full h-auto">
                        </div>
                    </div>
                </div>
                <div>
                    <div class="card bg-white p-8 h-full">
                        <h3 class="text-xl font-bold mb-4">Spring Security 防护</h3>
                        <p class="mb-4">从Spring Security 4.0开始，默认情况下会启用CSRF保护，会针对PATCH，POST，PUT和DELETE方法进行防护。</p>
                        
                        <div class="mb-6">
                            <h4 class="font-bold mb-2">表单设置CSRF Token</h4>
                            <pre class="code-block p-4 overflow-x-auto"><code class="language-html">&lt;form action="/login" method="POST"&gt;
    &lt;input type="hidden" 
           name="_csrf" 
           th:value="${_csrf.token}"&gt;
    &lt;!-- 其他表单字段 --&gt;
&lt;/form&gt;</code></pre>
                        </div>
                        
                        <div>
                            <h4 class="font-bold mb-2">关闭CSRF防护</h4>
                            <pre class="code-block p-4 overflow-x-auto"><code class="language-java">@Override
protected void configure(HttpSecurity http) throws Exception {
    http.csrf().disable();
}</code></pre>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </section>

    <!-- Password Encryption Section -->
    <section class="py-16 px-4 md:px-0">
        <div class="container mx-auto max-w-6xl">
            <div class="text-center mb-16">
                <span class="inline-block px-4 py-1 bg-primary-light text-primary rounded-full text-sm font-medium mb-3">安全实践</span>
                <h2 class="text-3xl font-bold mb-4">密码加密</h2>
                <div class="w-20 h-1 bg-primary mx-auto"></div>
            </div>

            <div class="grid md:grid-cols-2 gap-8 mb-12">
                <div>
                    <div class="card bg-white p-8 h-full">
                        <h3 class="text-xl font-bold mb-4">为什么需要加密？</h3>
                        <p class="mb-4">数据库中存储明文密码是极其危险的，一旦数据库泄露，攻击者可以轻易获取所有用户的密码。</p>
                        <div class="border rounded-lg overflow-hidden mb-4">
                            <img src="https://img-blog.csdnimg.cn/20190112095754535.png" alt="明文密码风险示意图" class="w-full h-auto">
                        </div>
                        <p>使用加密后的密码可以确保即使数据库泄露，攻击者也难以破解用户密码。</p>
                    </div>
                </div>
                <div>
                    <div class="card bg-white p-8 h-full">
                        <h3 class="text-xl font-bold mb-4">Spring Security 加密方案</h3>
                        <p class="mb-6">Spring Security 提供了 PasswordEncoder 接口来实现密码加密和验证：</p>
                        
                        <pre class="code-block p-4 overflow-x-auto"><code class="language-java">public interface PasswordEncoder {
    String encode(CharSequence rawPassword);
    boolean matches(CharSequence rawPassword, String encodedPassword);
}</code></pre>
                        
                        <div class="mt-6">
                            <h4 class="font-bold mb-2">推荐加密方式</h4>
                            <pre class="code-block p-4 overflow-x-auto"><code class="language-java">@Bean
public BCryptPasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
}</code></pre>
                            <div class="mt-2 flex items-center text-sm text-gray-600">
                                <i class="fas fa-check-circle mr-2 text-green-500"></i>
                                <span>BCrypt 是当前推荐的密码哈希算法</span>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </section>

    <!-- Token Authentication Section -->
    <section class="py-16 bg-gray-50 px-4 md:px-0">
        <div class="container mx-auto max-w-6xl">
            <div class="text-center mb-16">
                <span class="inline-block px-4 py-1 bg-primary-light text-primary rounded-full text-sm font-medium mb-3">现代认证</span>
                <h2 class="text-3xl font-bold mb-4">Token 认证</h2>
                <div class="w-20 h-1 bg-primary mx-auto"></div>
            </div>

            <div class="mb-12">
                <div class="card bg-white p-8 mb-8">
                    <h3 class="text-xl font-bold mb-4">什么是 Token？</h3>
                    <p class="mb-4">Token 是服务端生成的一串加密字符串，作为客户端请求的"令牌"。用户第一次使用账号密码成功登录后，服务器生成一个Token及Token失效时间并返回给客户端，以后客户端只需在有效时间内带上这个Token请求数据即可。</p>
                    <div class="border rounded-lg overflow-hidden">
                        <img src="https://cdn.nlark.com/yuque/0/2022/png/21449790/1651304757083-18db48cf-d8f7-40ff-9010-71659e580995.png" alt="Token认证流程" class="w-full h-auto">
                    </div>
                </div>

                <div class="grid md:grid-cols-2 gap-8">
                    <div>
                        <div class="card bg-white p-8 h-full">
                            <h3 class="text-xl font-bold mb-4">JWT 工具类</h3>
                            <pre class="code-block p-4 overflow-x-auto"><code class="language-java">public class JWTUtils {
    private static final String SECRET = "your-secret-key";
    private static final long EXPIRE = 1000 * 60 * 30; // 30分钟
    
    // 生成Token
    public static String createToken(Map&lt;String, Object&gt; claims) {
        return Jwts.builder()
            .setClaims(claims)
            .setExpiration(new Date(System.currentTimeMillis() + EXPIRE))
            .signWith(SignatureAlgorithm.HS512, SECRET)
            .compact();
    }
    
    // 解析Token
    public static Claims getClaim(String token) {
        return Jwts.parser()
            .setSigningKey(SECRET)
            .parseClaimsJws(token)
            .getBody();
    }
}</code></pre>
                        </div>
                    </div>
                    <div>
                        <div class="card bg-white p-8 h-full">
                            <h3 class="text-xl font-bold mb-4">Token 拦截器</h3>
                            <pre class="code-block p-4 overflow-x-auto"><code class="language-java">@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
    
    @Override
    protected void doFilterInternal(...) {
        String token = request.getHeader("token");
        Claims claim = JWTUtils.getClaim(token);
        
        if (claim != null) {
            String username = claim.get("username", String.class);
            UserDetails userDetails = userDetailsService.loadUserByUsername(username);
            
            UsernamePasswordAuthenticationToken authentication = 
                new UsernamePasswordAuthenticationToken(
                    userDetails, null, userDetails.getAuthorities());
            
            SecurityContextHolder.getContext()
                .setAuthentication(authentication);
        }
        
        chain.doFilter(request, response);
    }
}</code></pre>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </section>

    <script>
        // 初始化Mermaid图表
        mermaid.initialize({
            startOnLoad: true,
            theme: 'default',
            flowchart: {
                useMaxWidth: true,
                htmlLabels: true,
                curve: 'basis'
            },
            securityLevel: 'loose'
        });
        
        // 平滑滚动
        document.querySelectorAll('a[href^="#"]').forEach(anchor => {
            anchor.addEventListener('click', function (e) {
                e.preventDefault();
                document.querySelector(this.getAttribute('href')).scrollIntoView({
                    behavior: 'smooth'
                });
            });
        });
        
        // 卡片悬停效果
        const cards = document.querySelectorAll('.card');
        cards.forEach(card => {
            card.addEventListener('mouseenter', () => {
                card.style.transform = 'translateY(-5px)';
                card.style.boxShadow = '0 10px 20px rgba(0, 0, 0, 0.1)';
            });
            card.addEventListener('mouseleave', () => {
                card.style.transform = '';
                card.style.boxShadow = '';
            });
        });
    </script>
</body>
</html>
```